// const { parser } = require('../parser')

const test1 = () => {
    const tokenList = [
        {tokenValue: 'var', tokenType: TokenType.keyword},
        {tokenValue: 'o', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 2, tokenType: TokenType.number},
    ]
    const result = parser(tokenList)
    log('result:', result)
    const expect = {
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            tokenValue: 'o',
            tokenType: TokenType.variable,
        }, // 变量名
        value: {
            type: AstType.ExpressionBinary,
            operator: {
                tokenType: TokenType.plus,
                tokenValue: '+'
            },
            left: {
                tokenType: TokenType.number,
                tokenValue: 1,
            },
            right: {
                tokenType: TokenType.number,
                tokenValue: 2,
            }
        }
    }
    ensure(equals(result, expect), '### test1')
}


const test2 = () => {
    const code = `var o = {
        test: 123,
    }`
    // const tokenList = (new TokenList(code)).tokenList
    // log('tokenlist:', tokenList)

    const tokenList = [
        {tokenValue: 'var', tokenType: TokenType.keyword},
        {tokenValue: 'o', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: '{', tokenType: TokenType.curlyLeft},
        {tokenValue: "test", tokenType: TokenType.variable},
        {tokenValue: ':', tokenType: TokenType.colon},
        {tokenValue: 123, tokenType: TokenType.number},
        {tokenValue: ",", tokenType: TokenType.comma},
        {tokenValue: "key", tokenType: TokenType.variable},
        {tokenValue: ':', tokenType: TokenType.colon},
        {tokenValue: 99, tokenType: TokenType.number},
        {tokenValue: ",", tokenType: TokenType.comma},
        {tokenValue: "}", tokenType: TokenType.curlyRight},
    ]

    const result = parser(tokenList)
    log('result:', result)

    const expect = {
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            tokenValue: 'o',
            tokenType: TokenType.variable,
        }, // 变量名
        value: {
            type: AstType.ExpressionObject,
            properties: [
                {
                    type: AstType.PropertyObject,
                    key: {
                        tokenType: TokenType.variable,
                        tokenValue: 'test',
                    },
                    value: {
                        tokenType: TokenType.number,
                        tokenValue: 123,
                    }
                },
                {
                    type: AstType.PropertyObject,
                    key: {
                        tokenType: TokenType.variable,
                        tokenValue: 'key',
                    },
                    value: {
                        tokenType: TokenType.number,
                        tokenValue: 99,
                    }
                }
            ],
        }
    }
    ensure(equals(result, expect), '### test2')
}

const test_var_object = () => {
    const code = `var o = {
        test: 123,
    }`
    // const tokenList = (new TokenList(code)).tokenList
    // log('tokenlist:', tokenList)

    const tokenList = [
        {tokenValue: 'var', tokenType: TokenType.keyword},
        {tokenValue: 'o', tokenType: TokenType.variable},
        {tokenValue: '=', tokenType: TokenType.assign},
        {tokenValue: '{', tokenType: TokenType.curlyLeft},
        {tokenValue: "test", tokenType: TokenType.variable},
        {tokenValue: ':', tokenType: TokenType.colon},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},

        {tokenValue: ",", tokenType: TokenType.comma},
        {tokenValue: "key", tokenType: TokenType.variable},
        {tokenValue: ':', tokenType: TokenType.colon},
        {tokenValue: 99, tokenType: TokenType.number},
        {tokenValue: ",", tokenType: TokenType.comma},
        {tokenValue: "}", tokenType: TokenType.curlyRight},
    ]

    const result = parser(tokenList)
    log('result:', result)

    const expect = {
        type: AstType.DeclarationVariable,
        kind: 'var',
        variable: {
            tokenValue: 'o',
            tokenType: TokenType.variable,
        }, // 变量名
        value: {
            type: AstType.ExpressionObject,
            properties: [
                {
                    type: AstType.PropertyObject,
                    key: {
                        tokenType: TokenType.variable,
                        tokenValue: 'test',
                    },
                    value: {
                        type: AstType.ExpressionBinary,
                        operator: {
                            tokenType: TokenType.plus,
                            tokenValue: '+'
                        },
                        left: {
                            tokenType: TokenType.number,
                            tokenValue: 1,
                        },
                        right: {
                            arguments: [
                                {
                                    tokenType: TokenType.number,
                                    tokenValue: 2,
                                },
                                {
                                    tokenType: TokenType.number,
                                    tokenValue: 3,
                                },
                            ],
                            callee: {
                                tokenType: TokenType.variable,
                                tokenValue: 'add',
                            },
                            type: AstType.ExpressionCall,
                        }
                    }
                },
                {
                    type: AstType.PropertyObject,
                    key: {
                        tokenType: TokenType.variable,
                        tokenValue: 'key',
                    },
                    value: {
                        tokenType: TokenType.number,
                        tokenValue: 99,
                    }
                }
            ],
        }
    }
    ensure(equals(result, expect), '### test_var_object')
}

// 表达式测试
const test3 = () => {
    const tokenList = [
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
    ]
    const result = parser(tokenList)
    log('result:', result)

    // const expect = {
    //     type: AstType.DeclarationVariable,
    //     kind: 'var',
    //     variable: {
    //         value: 'o',
    //         type: TokenType.variable,
    //     }, // 变量名
    //     value: {
    //         type: AstType.ExpressionObject,
    //         properties: [
    //             {
    //                 type: AstType.PropertyObject,
    //                 key: {
    //                     type: TokenType.variable,
    //                     value: 'test',
    //                 },
    //                 value: {
    //                     type: TokenType.number,
    //                     value: 123,
    //                 }
    //             }
    //         ],
    //     }
    // }
    // ensure(equals(result, expect), '### test1')
}

const test4 = () => {
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
        {tokenValue: ';', tokenType: TokenType.semicolon},
    ]
    // log(lastIndexOf(tokenList, {tokenValue: 2, tokenType: TokenType.number}))
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}

const test5 = () => {
    // var a = 1 + add(1, 2) + 3
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 3, tokenType: TokenType.number},

        {tokenValue: ';', tokenType: TokenType.semicolon},
    ]
    // log(lastIndexOf(tokenList, {tokenValue: 2, tokenType: TokenType.number}))
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}

// 最简单的测试
const test6 = () => {
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ';', tokenType: TokenType.semicolon},
    ]
    // log(lastIndexOf(tokenList, {tokenValue: 2, tokenType: TokenType.number}))
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}
const test13 = () => {
    // 1 * ( 3 + 4 )
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '*', tokenType: TokenType.multiply},

        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 4, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},

        {tokenValue: ';', tokenType: TokenType.semicolon},
    ]
    // log(lastIndexOf(tokenList, {tokenValue: 2, tokenType: TokenType.number}))
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}
const test7 = () => {
    // 1 + add(1, 2) * ( 3 + 4 )
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
        {tokenValue: '*', tokenType: TokenType.multiply},

        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 4, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},

        {tokenValue: ';', tokenType: TokenType.semicolon},
    ]
    // log(lastIndexOf(tokenList, {tokenValue: 2, tokenType: TokenType.number}))
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}


const test8 = () => {
    const tokenList = [
        {tokenValue: 1, tokenType: TokenType.number},
    ]
    // 先把表达式跑一遍
    const result = parser(tokenList)
    log('result:', result)
}

const test_function_call = () => {
    // 参数也可能是函数调用，也可能是计算表达式
    // 所以需要切分
    // const code = `var o = {
    //     test: 123,
    // }`
    // const tokenList = (new TokenList(code)).tokenList
    // log('tokenlist:', tokenList)

    const tokenList = [
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 3, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
    ]

    const result = parser(tokenList)
    log('result:', result)

    const expect = {
        arguments: [
            {
                type: AstType.ExpressionBinary,
                operator: {
                    tokenType: TokenType.plus,
                    tokenValue: '+'
                },
                left: {
                    tokenType: TokenType.number,
                    tokenValue: 2,
                },
                right: {
                    tokenType: TokenType.number,
                    tokenValue: 3,
                }
            },
            {
                tokenType: TokenType.number,
                tokenValue: 3,
            },
        ],
        callee: {
            tokenType: TokenType.variable,
            tokenValue: 'add',
        },
        type: AstType.ExpressionCall,

    }
    ensure(equals(result, expect), '### test_function_call')
}


const test_function_call_call = () => {
    // add(add(1,2), 1+3)
    // 参数也可能是函数调用，也可能是计算表达式
    // 所以需要切分
    // const code = `add(add(1,2), 1+3)`
    // const tokenList = (new TokenList(code)).tokenList
    // log('tokenlist:', tokenList)

    const tokenList = [
        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},

        {tokenValue: 'add', tokenType: TokenType.variable},
        {tokenValue: '(', tokenType: TokenType.parenthesesLeft},
        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: ',', tokenType: TokenType.comma},
        {tokenValue: 2, tokenType: TokenType.number},
        {tokenValue: ')', tokenType: TokenType.parenthesesRight},

        {tokenValue: ',', tokenType: TokenType.comma},

        {tokenValue: 1, tokenType: TokenType.number},
        {tokenValue: '+', tokenType: TokenType.plus},
        {tokenValue: 3, tokenType: TokenType.number},

        {tokenValue: ')', tokenType: TokenType.parenthesesRight},
    ]

    const result = parser(tokenList)
    log('result:', result)

    const expect = {
        arguments: [
            {
                type: AstType.ExpressionCall,
                callee: {
                    tokenType: TokenType.variable,
                    tokenValue: 'add',
                },
                arguments: [
                    {
                        tokenType: TokenType.number,
                        tokenValue: 1,
                    },
                    {
                        tokenType: TokenType.number,
                        tokenValue: 2,
                    },
                ],
            },
            {
                type: AstType.ExpressionBinary,
                operator: {
                    tokenType: TokenType.plus,
                    tokenValue: '+'
                },
                left: {
                    tokenType: TokenType.number,
                    tokenValue: 1,
                },
                right: {
                    tokenType: TokenType.number,
                    tokenValue: 3,
                }
            },
        ],
        callee: {
            tokenType: TokenType.variable,
            tokenValue: 'add',
        },
        type: AstType.ExpressionCall,
    }
    ensure(equals(result, expect), '### test_function_call_call')
}


// const test = () => {
//     log('test_')
//     // test1()
//     // test2()
//     // test_var_object()
//     // test3()
//     // test5()
//     // test6()
//     // test7()
//     // test8()
//
//     // test_function_call()
//     test_function_call_call()
// }

// test()